package client

import (
	. "chess_platform/internal/common"
	"fmt"
	"github.com/astaxie/beego/orm"
	"time"
)

//上下分
//新增上下分
func newContest(data map[string]interface{}, multiOrm ...orm.Ormer) (int64, error) {
	o := NewOrm(multiOrm, DBChess)
	values, sql := InsertSql(TableClubScore, data)
	result, err := o.Raw(sql, values).Exec()
	if err != nil {
		return 0, err
	}
	return result.LastInsertId()
}

//调整俱乐部成员的积分
func updateClubScore(clubId, uid, score, fee int64, multiOrm ...orm.Ormer) (int64, error) {
	o := NewOrm(multiOrm, DBChess)
	sql := fmt.Sprintf(`UPDATE %v SET score = score + %v,fee = fee + %v WHERE cid = %v AND uid = %v`,
		TableClubMember, score, fee, clubId, uid)
	result, err := o.Raw(sql).Exec()
	if err != nil {
		return 0, err
	}
	return result.RowsAffected()
}

//调整积分，并写记录
func ChangeScore(clubId, uid, score, fee, operatorUid int64) error {
	o := NewDBOrm(DBChess)
	o.Begin()
	defer o.Rollback()
	data := map[string]interface{}{
		"club_id":      clubId,
		"uid":          uid,
		"score":        score,
		"fee":          fee,
		"operator_uid": operatorUid,
		"create_time":  time.Now().Unix(),
	}
	_, err := newContest(data, o)
	if err != nil {
		o.Rollback()
		return err
	}
	_, err = updateClubScore(clubId, uid, score, fee, o)
	if err != nil {
		o.Rollback()
		return err
	}
	return o.Commit()
}

type MemberScore struct {
	Uid        int64 `json:"uid"`
	Score      int64 `json:"score"`
	FrozeScore int64 `json:"froze_score"`
	Fee        int64 `json:"fee"`
}

//获取俱乐部成员的积分数
//当不传uid时表示获取俱乐部所有成员的积分,传了uid获取指定uid的积分
func ListClubMemberScore(clubId, uid int64, multiOrm ...orm.Ormer) ([]MemberScore, error) {
	var sql string
	if uid == 0 {
		sql = fmt.Sprintf(`
			SELECT
				uid,score,froze_score,fee
			FROM
				%v
			WHERE
				cid = %v AND status IN (%v,%v)
		`, TableClubMember, clubId, ClubMemberNormal, ClubMemberMute)
	} else {
		sql = fmt.Sprintf(`
			SELECT
				uid,score,froze_score,fee
			FROM
				%v
			WHERE
				cid = %v AND uid = %v
		`, TableClubMember, clubId, uid)
	}
	o := NewOrm(multiOrm, DBChess)
	var ms []MemberScore
	_, err := o.Raw(sql).QueryRows(&ms)
	return ms, err
}

//清除单个俱乐部成员的积分
func ClearScore(clubId, operatorUid, uid, typ int64) (bool, error) {
	ms, err := ListClubMemberScore(clubId, uid)
	if err != nil {
		return false, err
	}
	var ok bool
	for _, v := range ms {
		if v.FrozeScore != 0 { //正式游戏的不能清除积分及表情
			ok = true
			continue
		}
		//如果积分与表情都为0，就没有必要清了
		if v.Score == 0 && v.Fee == 0 {
			continue
		}
		if typ == 0 {
			err = ChangeScore(clubId, v.Uid, -v.Score, -v.Fee, operatorUid)
		} else if typ == 1 {
			if v.Score == 0 {
				continue
			}
			err = ChangeScore(clubId, v.Uid, -v.Score, 0, operatorUid)
		} else if typ == 2 {
			if v.Fee == 0 {
				continue
			}
			err = ChangeScore(clubId, v.Uid, 0, -v.Fee, operatorUid)
		}
		if err != nil {
			return false, err
		}
	}
	return ok, nil
}

//清除表情统计
func ClearFee(clubId int64) (int64, error) {
	data := map[string]interface{}{
		"contest_time": time.Now().Unix(),
	}
	return UpdateClub(data, clubId)
}

//上下分流水记录
func updateScoreTrans(club map[string]interface{}, id, clubId int64, multiOrm ...orm.Ormer) (int64, error) {
	o := NewOrm(multiOrm, DBChess)
	var condition string
	if id == 0 {
		condition = fmt.Sprintf(`club_id = %v`, clubId)
	} else {
		condition = fmt.Sprintf(`id = %v AND club_id = %v`, id, clubId)
	}
	values, sql := UpdateSql(TableClubScore, club, condition)
	result, err := o.Raw(sql, values).Exec()
	if err != nil {
		return 0, err
	}
	return result.RowsAffected()
}

//清除积分流水记录
func ClearScoreRecord(id, clubId int64) (int64, error) {
	data := map[string]interface{}{
		"is_delete": 1,
	}
	return updateScoreTrans(data, id, clubId)
}

type Score struct {
	TotalScore   int64 `json:"total_score"`   //积分总数
	TotalFee     int64 `json:"total_fee"`     //表情总数
	YesterdayFee int64 `json:"yesterday_fee"` //昨日表情
	TodayFee     int64 `json:"today_fee"`     //今日表情
}

//统计
func StatScore(clubId int64) (Score, error) {
	var (
		contestTime  int64
		yStart, yEnd int64
	)
	now := time.Now().Unix()
	tStart, tEnd := StartEndTimeByTimestamp(now - 86400) //昨天的开始及起始时间

	o := NewDBOrm(DBChess)
	//统计积分和表情的起始时间
	sql := fmt.Sprintf(`SELECT contest_time FROM %v WHERE id = %v`, TableClub, clubId)
	o.Raw(sql).QueryRow(&contestTime)

	if contestTime <= tStart {
		yStart = tStart
		yEnd = tEnd
	} else if contestTime > tStart && contestTime <= tEnd {
		yStart = contestTime
		yEnd = tEnd
	} else if contestTime > tEnd {
		yStart = now //因为清除时间大于tEnd，所以昨日表情为0
		yEnd = contestTime
	}

	//统计总积分
	sqlTotalScore := fmt.Sprintf(`
		SELECT
			IF(SUM(score) is NULL,0,SUM(score)) AS total_score,
			IF(SUM(froze_score) is NULL,0,SUM(froze_score)) AS total_frozen_score
		FROM
			%v
		WHERE
			cid = %v AND status IN (%v,%v)
	`, TableClubMember, clubId, ClubMemberNormal, ClubMemberMute)
	//统计昨日的表情
	sqlYesterday := fmt.Sprintf(`
		SELECT
			IF(SUM(r.fee) is NULL,0,SUM(r.fee)) AS yesterday_fee
		FROM
			%v AS p
		LEFT JOIN
			%v AS r
		ON p.tableid = r.tableid
		WHERE
			p.clubid = %v AND p.endtime >= %v AND p.endtime <= %v
	`, TableRoom, TableRoomLog, clubId, yStart, yEnd)
	//统计今日的表情
	sqlToday := fmt.Sprintf(`
		SELECT
			IF(SUM(r.fee) is NULL,0,SUM(r.fee)) AS today_fee
		FROM
			%v AS p
		LEFT JOIN
			%v AS r
		ON p.tableid = r.tableid
		WHERE
			p.clubid = %v AND p.endtime >= %v AND p.endtime <= %v
	`, TableRoom, TableRoomLog, clubId, yEnd, now)

	//统计总表情数
	sqlTotalFee := fmt.Sprintf(`
		SELECT
			IF(SUM(r.fee) is NULL,0,SUM(r.fee)) AS total_fee
		FROM
			%v AS p
		LEFT JOIN
			%v AS r
		ON p.tableid = r.tableid
		WHERE
			p.clubid = %v AND p.endtime >= %v AND p.endtime <= %v
	`, TableRoom, TableRoomLog, clubId, contestTime, now)

	var s Score
	var totalFrozeScore int64
	err := o.Raw(sqlTotalScore).QueryRow(&s.TotalScore, &totalFrozeScore)
	if err != nil {
		return s, err
	}
	s.TotalScore = s.TotalScore + totalFrozeScore

	if contestTime > tEnd {
		//今天清除了表情，所以昨日的表情不用统计了，直接是为0
		s.YesterdayFee = 0
	} else {
		err = o.Raw(sqlYesterday).QueryRow(&s.YesterdayFee)
		if err != nil {
			return s, err
		}
	}
	err = o.Raw(sqlToday).QueryRow(&s.TodayFee)
	if err != nil {
		return s, err
	}
	err = o.Raw(sqlTotalFee).QueryRow(&s.TotalFee)
	if err != nil {
		return s, err
	}
	return s, nil
}

//积分操作记录(流水)
func ListScoreTrans(p ListParams, clubId, uid int64) ([]orm.Params, int64, error) {
	limit := (p.PageIndex - 1) * p.PageSize
	var sql string
	//头像,ID,nickname,score,operator_uid,create_time
	where := fmt.Sprintf(`club_id = %v AND is_delete = 0`, clubId)
	if uid != 0 {
		where = fmt.Sprintf(`club_id = %v AND is_delete = 0 AND uid = %v`, clubId, uid)
	}
	sql = fmt.Sprintf(`
			SELECT
				*
			FROM
				%v
			WHERE
				%v
			ORDER BY
				create_time DESC
			LIMIT %v,%v
	`, TableClubScore, where, limit, p.PageSize)

	o := NewDBOrm(DBChess)
	var st []orm.Params
	var tt []ScoreTrans
	_, err := o.Raw(sql).QueryRows(&tt)
	if CheckError(err) {
		return st, 0, err
	}
	for _, v := range tt {
		u, _ := QueryUserInfoById(v.Uid)
		st = append(st, map[string]interface{}{
			"id":           v.Id,
			"club_id":      v.ClubId,
			"uid":          v.Uid,
			"score":        v.Score,
			"fee":          v.Fee,
			"operator_uid": v.OperatorUid,
			"create_time":  v.CreateTime,
			"nickname":     u.Nickname,
			"imageurl":     u.ImageUrl,
		})
	}
	sql = fmt.Sprintf(`
		SELECT
			COUNT(1)
		FROM
			%v
		WHERE
			%v
	`, TableClubScore, where)
	var count int64
	err = o.Raw(sql).QueryRow(&count)
	return st, count, err
}

//俱乐部积分
func ListClubScore(p ListParams, clubId, uid int64) ([]orm.Params, int64, error) {
	limit := (p.PageIndex - 1) * p.PageSize
	var sql string
	//头像,ID,nickname,score,表情数
	if uid == 0 {
		sql = fmt.Sprintf(`
			SELECT
				uid,score,froze_score,fee
			FROM
				%v
			WHERE
				cid = %v AND status IN (%v,%v)
			LIMIT %v,%v
		`, TableClubMember, clubId, ClubMemberNormal, ClubMemberMute, limit, p.PageSize)
	} else {
		sql = fmt.Sprintf(`
			SELECT
				uid,score,froze_score,fee
			FROM
				%v
			WHERE
				cid = %v AND uid = %v
		`, TableClubMember, clubId, uid)
	}
	o := NewDBOrm(DBChess)
	var st []orm.Params
	var tt []ClubScore
	_, err := o.Raw(sql).QueryRows(&tt)
	if CheckError(err) {
		return st, 0, err
	}
	for _, v := range tt {
		u, _ := QueryUserInfoById(v.Uid)
		st = append(st, map[string]interface{}{
			"uid":         v.Uid,
			"froze_score": v.FrozeScore,
			"score":       v.Score,
			"fee":         v.Fee,
			"nickname":    u.Nickname,
			"imageurl":    u.ImageUrl,
		})
	}

	if uid != 0 && len(tt) == 1 {
		return st, 1, nil
	} else if uid != 0 && len(tt) == 0 {
		return st, 0, nil
	}
	sql = fmt.Sprintf(`
		SELECT
			COUNT(1)
		FROM
			%v
		WHERE
			cid = %v AND status IN (%v,%v)
	`, TableClubMember, clubId, ClubMemberMute, ClubMemberNormal)
	var count int64
	err = o.Raw(sql).QueryRow(&count)
	return st, count, err
}

//俱乐部成员打积分场，输赢的次数
func ListPlayerWinLost(p ListParams, clubId, typ int64) ([]orm.Params, int64, error) {
	var orderName string
	if typ == 1 {
		orderName = "win_num"
	} else if typ == 2 {
		orderName = "lose_num"
	}
	limit := (p.PageIndex - 1) * p.PageSize
	sql := fmt.Sprintf(`
			SELECT
				uid,win_num,lose_num
			FROM
				%v
			WHERE
				cid = %v AND status IN (%v,%v)
			ORDER BY
				%v DESC
			LIMIT %v,%v
	`, TableClubMember, clubId, ClubMemberNormal, ClubMemberMute, orderName, limit, p.PageSize)
	o := NewDBOrm(DBChess)
	var st []orm.Params
	var tt []ClubScore
	_, err := o.Raw(sql).QueryRows(&tt)
	if CheckError(err) {
		return st, 0, err
	}
	for _, v := range tt {
		u, _ := QueryUserInfoById(v.Uid)
		st = append(st, map[string]interface{}{
			"uid":      v.Uid,
			"win_num":  v.WinNum,
			"lose_num": v.LoseNum,
			"nickname": u.Nickname,
			"imageurl": u.ImageUrl,
		})
	}

	sql = fmt.Sprintf(`
		SELECT
			COUNT(1)
		FROM
			%v
		WHERE
			cid = %v AND status IN (%v,%v)
	`, TableClubMember, clubId, ClubMemberMute, ClubMemberNormal)
	var count int64
	err = o.Raw(sql).QueryRow(&count)
	return st, count, err
}
